#ifndef CALIBRATOR_H
#define CALIBRATOR_H
#include <string>
#include <QObject>
#include "settings.h"

int calMainRun(int argc, char* argv[]);

void doCal(string path);

class Calibrator : public QObject {
    Q_OBJECT
private:
    const int m_argc;
    char** m_argv;
    enum { DETECTION = 0, CAPTURING = 1, CALIBRATED = 2 };

public:
    explicit Calibrator(int argc, char** m_argv, QObject* parent = nullptr);
    ~Calibrator();
    // 标定主函数
    int calMainRun();
    // 校准函数
    void doCal(string path);

private:
    // 标定并保存标定参数
    bool runCalibrationAndSave(Settings& s, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs,
        vector<vector<Point2f> > imagePoints, float grid_width, bool release_object);

    // 计算映射误差
    double computeReprojectionErrors(const vector<vector<Point3f> >& objectPoints,
        const vector<vector<Point2f> >& imagePoints,
        const vector<Mat>& rvecs, const vector<Mat>& tvecs,
        const Mat& cameraMatrix, const Mat& distCoeffs,
        vector<float>& perViewErrors, bool fisheye);

    // 根据标定板类型计算角点的世界坐标
    void calcBoardCornerPositions(Size boardSize, float squareSize, vector<Point3f>& corners,
        Settings::Pattern patternType /*= Settings::CHESSBOARD*/);

    // 标定
    bool runCalibration(Settings& s, Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
        vector<vector<Point2f> > imagePoints, vector<Mat>& rvecs, vector<Mat>& tvecs,
        vector<float>& reprojErrs, double& totalAvgErr, vector<Point3f>& newObjPoints,
        float grid_width, bool release_object);

    // 保存相机标定参数
    void saveCameraParams(Settings& s, Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
        const vector<Mat>& rvecs, const vector<Mat>& tvecs,
        const vector<float>& reprojErrs, const vector<vector<Point2f> >& imagePoints,
        double totalAvgErr, const vector<Point3f>& newObjPoints);
};

#endif // CALIBRATOR_H
